#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include<signal.h>

#include"log.hpp"
#include"Threadpool.hpp"
#include"Task.hpp"

namespace server
{enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };
  static const uint16_t gport=8080;
  static const int gbacklog=5;
  //static const std::string ip="0.0.0.0";
  class Tcpserver
  { public:
     Tcpserver(const uint16_t &port=gport):_listensock(-1),_port(port)
{}
    void initServer()
    {   //1.创建套接字
        _listensock=socket(AF_INET,SOCK_STREAM,0);
        if(_listensock<0)
        {
            logMessage(FATAL, "create socket error");
                exit(SOCKET_ERR);
        }
        logMessage(NORMAL,"create socket success");
        //2.绑定服务端的网络信息到结构体上
           struct sockaddr_in local;
            memset(&local, 0, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;//任意ip
            if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
            {
                logMessage(FATAL, "bind socket error");
                exit(BIND_ERR);
            }
            logMessage(NORMAL, "bind socket success");
            //3.设置套接字为监听状态
            if(listen(_listensock,gbacklog)<0)
            {
                logMessage(FATAL, "listen socket error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL,"listensocket success");
    }
    void start()
    { //signal(SIGCHLD,SIG_IGN);//忽略子进程退出结果，就不用等待子进程了
      Threadpool<Task>::getInstance()->run();
      logMessage(NORMAL, "Thread init success");
      for(;;)
      {
        //4.获取链接
        struct sockaddr_in peer;
        socklen_t len=sizeof(peer);
        //建立链接是在accept之前，客户端os发出链接请求，服务端os接受
        int sock =accept(_listensock,(struct sockaddr*)&peer,&len);//sock为得到客户端传递信息的文件描述符
        if(sock<0)
        {
            logMessage(ERROR, "accept error, next");
                    continue;

        }
        logMessage(NORMAL, "accept success 文件描述符：%d", sock);
        logMessage(ERROR, "accept error, next");
        logMessage(FATAL, "fatal error, next");
        logMessage(DEBUG, "测试 error, next");
        logMessage(WARNING, "警告, next");
        logMessage(ERROR, "错误, next");
        //多进程版1 关闭子进程，让子进程的子进程执行io，这样这个进程由os获取退出资源
        //   int n =fork();
        //   if(n==0)
        //   {close(_listensock);//因为子进程不需要进行监听
        //   serviceIO(sock);
        //   close(sock);
        //   exit(0);
        //   }
        //   close(sock);//客户端退出，必须要关闭文件描述符
    
        // 多线程方式
        //1.线程分离，就不用阻塞等待

        //通过管道的线程池

        Threadpool<Task>::getInstance()->push(Task(sock)); // 单例模式下传递任务，之后的事情就是线程来进行竞争串行执行了。
       }
      
    }
  
   ~Tcpserver(){}

    private:
    int _listensock;
    uint16_t _port;
  };




}